﻿using FySystem.IO;
using FySystem.Secure;
using System;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FyCacheClient
{
    internal class PackageCreater
    {
        //版本号：1
        internal static byte[] ver = BitConverter.GetBytes(1);

        /// <summary>
        /// 创建设置值的包
        /// </summary>
        /// <param name="byteAuth"></param>
        /// <param name="key"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        internal static List<byte> PackSet(ref byte[] byteAuth, string key, ushort dbIndex, CSon data, ref byte[] requestId)
        {
            List<byte> res = new List<byte>();
            try
            {
                //用户密码
                res.AddRange(byteAuth);

                //版本
                res.AddRange(ver);

                //请求id
                requestId = Guid.NewGuid().ToByteArray();
                res.AddRange(requestId);

                //缓存索引
                res.AddRange(BitConverter.GetBytes(dbIndex));

                //指令
                res.Add(0x00);
                res.Add(0x00);

                //key
                byte[] bkey = Encoding.UTF8.GetBytes(key);
                res.AddRange(BitConverter.GetBytes((ushort)bkey.Length));           //2字节key长度
                res.AddRange(bkey);

                //数据
                if (data != null)
                    data.ToBytesList(ref res);
            }
            catch (Exception)
            {
                throw;
            }
            return res;
        }

        /// <summary>
        /// 创建设置值的包
        /// </summary>
        /// <param name="byteAuth"></param>
        /// <param name="key"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        internal static List<byte> PackSet(ref byte[] byteAuth, string key, ushort dbIndex, ref byte[] data, ref byte[] requestId)
        {
            List<byte> res = new List<byte>();
            try
            {
                //用户密码
                res.AddRange(byteAuth);

                //版本
                res.AddRange(ver);

                //请求id
                requestId = Guid.NewGuid().ToByteArray();
                res.AddRange(requestId);

                //缓存索引
                res.AddRange(BitConverter.GetBytes(dbIndex));

                //指令
                res.Add(0x00);
                res.Add(0x00);

                //key
                byte[] bkey = Encoding.UTF8.GetBytes(key);
                res.AddRange(BitConverter.GetBytes((ushort)bkey.Length));           //2字节key长度
                res.AddRange(bkey);

                //数据
                if (data != null)
                    res.AddRange(data);
            }
            catch (Exception)
            {
                throw;
            }
            return res;
        }

        /// <summary>
        /// 创建删除的包
        /// </summary>
        /// <param name="byteAuth"></param>
        /// <param name="key"></param>
        /// <param name="dbIndex"></param>
        /// <param name="requestId"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        internal static List<byte> PackDelete(ref byte[] byteAuth, string key, ushort dbIndex, ref byte[] requestId)
        {
            List<byte> res = new List<byte>();
            try
            {
                //用户密码
                res.AddRange(byteAuth);

                //版本
                res.AddRange(ver);

                //请求id
                requestId = Guid.NewGuid().ToByteArray();
                res.AddRange(requestId);

                //缓存索引
                res.AddRange(BitConverter.GetBytes(dbIndex));

                //指令
                res.Add(0x00);
                res.Add(0x03);

                //key
                byte[] bkey = Encoding.UTF8.GetBytes(key);
                res.AddRange(bkey);
            }
            catch (Exception)
            {
                throw;
            }
            return res;
        }

        /// <summary>
        /// 创建获取数据的包
        /// </summary>
        /// <param name="byteAuth"></param>
        /// <param name="key"></param>
        /// <param name="dbIndex"></param>
        /// <param name="requestId"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        internal static List<byte> PackGet(ref byte[] byteAuth, string key, ushort dbIndex, ref byte[] requestId)
        {
            List<byte> res = new List<byte>();
            try
            {
                //用户密码
                res.AddRange(byteAuth);

                //版本
                res.AddRange(ver);

                //请求id
                requestId = Guid.NewGuid().ToByteArray();
                res.AddRange(requestId);

                //缓存索引
                res.AddRange(BitConverter.GetBytes(dbIndex));

                //指令
                res.Add(0x00);
                res.Add(0x01);

                //key
                res.AddRange(Encoding.UTF8.GetBytes(key));
            }
            catch (Exception)
            {
                throw;
            }
            return res;
        }

        /// <summary>
        /// 创建判断键是否存在的包
        /// </summary>
        /// <param name="byteAuth"></param>
        /// <param name="key"></param>
        /// <param name="dbIndex"></param>
        /// <param name="requestId"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        internal static List<byte> PackIsExist(ref byte[] byteAuth, string key, ushort dbIndex, ref byte[] requestId)
        {
            List<byte> res = new List<byte>();
            try
            {
                //用户密码
                res.AddRange(byteAuth);

                //版本
                res.AddRange(ver);

                //请求id
                requestId = Guid.NewGuid().ToByteArray();
                res.AddRange(requestId);

                //缓存索引
                res.AddRange(BitConverter.GetBytes(dbIndex));

                //指令
                res.Add(0x00);
                res.Add(0x02);

                //key
                res.AddRange(Encoding.UTF8.GetBytes(key));
            }
            catch (Exception)
            {
                throw;
            }
            return res;
        }

        /// <summary>
        /// 创建批量设置包
        /// </summary>
        /// <param name="byteAuth"></param>
        /// <param name="csonKey"></param>
        /// <param name="datas"></param>
        /// <param name="startIndex"></param>
        /// <param name="endIndex"></param>
        /// <param name="requestId"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        internal static List<byte> PackBatchSet(ref byte[] byteAuth, ushort dbIndex, string csonKey, List<CSon> datas, int startIndex, int endIndex, ref byte[] requestId)
        {
            List<byte> res = new List<byte>();
            try
            {
                //用户密码
                res.AddRange(byteAuth);

                //版本
                res.AddRange(ver);

                //请求id
                requestId = Guid.NewGuid().ToByteArray();
                res.AddRange(requestId);

                //缓存索引
                res.AddRange(BitConverter.GetBytes(dbIndex));

                //指令
                res.Add(0x00);
                res.Add(0x04);

                int tmpIndex = 0;

                for(int i = startIndex; i <= endIndex; i++)
                {
                    if (datas[i] == null)
                        throw new Exception($"第{i}个元素为null");

                    //单个元素的key
                    byte[] bKey = Encoding.UTF8.GetBytes(datas[i][csonKey].StringValue);
                    res.AddRange(BitConverter.GetBytes((ushort)bKey.Length));
                    res.AddRange(bKey);

                    //数据
                    //4字节长度的占位
                    tmpIndex = res.Count;
                    res.Add(0x00);
                    res.Add(0x00);
                    res.Add(0x00);
                    res.Add(0x00);

                    datas[i].ToBytesList(ref res);
                    byte[] bl = BitConverter.GetBytes(res.Count - tmpIndex - 4);
                    for (int j = 0; j < 4; j++)
                        res[tmpIndex + j] = bl[j];
                }
            }
            catch (Exception)
            {
                throw;
            }
            return res;
        }

        /// <summary>
        /// 创建订阅包
        /// </summary>
        /// <param name="byteAuth"></param>
        /// <param name="topic"></param>
        /// <param name="clientId"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        internal static List<byte> PackSubscribe(ref byte[] byteAuth, string topic)
        {
            List<byte> res = new List<byte>();
            try
            {
                //用户密码
                res.AddRange(byteAuth);

                //版本
                res.AddRange(ver);

                //请求id
                res.AddRange(Guid.NewGuid().ToByteArray());

                //缓存索引（预留，本包中无效）
                res.Add(0x00);
                res.Add(0x00);

                //指令
                res.Add(0xff);
                res.Add(0x00);

                //主题
                res.AddRange(Encoding.UTF8.GetBytes(topic));
            }
            catch (Exception)
            {
                throw;
            }
            return res;
        }

        /// <summary>
        /// 该函数的dbindex是不需要的，这里打包进去方便服务端解析
        /// </summary>
        /// <param name="byteAuth"></param>
        /// <param name="topic"></param>
        /// <param name="message"></param>
        /// <param name="requestId"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        internal static List<byte> PackPublish(ref byte[] byteAuth, string topic, byte[] clientId, byte[] message, ref byte[] requestId)
        {
            List<byte> res = new List<byte>();
            try
            {
                //用户密码
                res.AddRange(byteAuth);

                //版本
                res.AddRange(ver);

                //请求id
                res.AddRange(Guid.NewGuid().ToByteArray());

                //缓存索引（预留，本包中无效）
                res.Add(0x00);
                res.Add(0x00);

                //指令
                res.Add(0xff);
                res.Add(0x01);

                //主题
                byte[] bTopic = Encoding.UTF8.GetBytes(topic);
                res.AddRange(BitConverter.GetBytes((ushort)bTopic.Length));
                res.AddRange(bTopic);

                //clientId
                res.AddRange(BitConverter.GetBytes((ushort)clientId.Length));
                res.AddRange(clientId);

                //消息内容
                res.AddRange(message);
            }
            catch (Exception)
            {
                throw;
            }
            return res;
        }

        /// <summary>
        /// 取消订阅
        /// </summary>
        /// <param name="byteAuth"></param>
        /// <param name="topic"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        internal static List<byte> PackUnSubscribe(ref byte[] byteAuth, string topic)
        {
            List<byte> res = new List<byte>();
            try
            {
                //用户密码
                res.AddRange(byteAuth);

                //版本
                res.AddRange(ver);

                //请求id
                res.AddRange(Guid.NewGuid().ToByteArray());

                //缓存索引（预留，本包中无效）
                res.Add(0x00);
                res.Add(0x00);

                //指令
                res.Add(0xff);
                res.Add(0x02);

                //主题
                res.AddRange(Encoding.UTF8.GetBytes(topic));
            }
            catch (Exception)
            {
                throw;
            }
            return res;
        }

        /// <summary>
        /// 创建获取服务器版本的包
        /// </summary>
        /// <param name="byteAuth"></param>
        /// <param name="dbIndex"></param>
        /// <param name="requestId"></param>
        /// <returns></returns>
        internal static List<byte> PackServerVer(ref byte[] byteAuth, ushort dbIndex, ref byte[] requestId)
        {
            List<byte> res = new List<byte>();
            try
            {
                //用户密码
                res.AddRange(byteAuth);

                //版本
                res.AddRange(ver);

                //请求id
                requestId = Guid.NewGuid().ToByteArray();
                res.AddRange(requestId);

                //缓存索引（该指令中无效，只是占位）
                res.AddRange(BitConverter.GetBytes(dbIndex));

                //指令
                res.Add(0xff);
                res.Add(0xff);
            }
            catch (Exception)
            {
                throw;
            }
            return res;
        }
    }
}
